package com.feishi.project.webbase.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.feishi.project.webbase.bean.WebResult;
import com.feishi.project.webbase.service.AuthenticationAccessDeniedHandler;
import com.feishi.project.webbase.service.UserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.CorsConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.util.DigestUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


/**
 * ┌─┐       ┌─┐
 * ┌──┘ ┴───────┘ ┴──┐
 * │                 │
 * │       ───       │
 * │  ─┬┘       └┬─  │
 * │                 │
 * │       ─┴─       │
 * │                 │
 * └───┐         ┌───┘
 * │         │
 * │         │
 * │         │
 * │         └──────────────┐
 * │                        │
 * │                        ├─┐
 * │                        ┌─┘
 * │                        │
 * └─┐  ┐  ┌───────┬──┐  ┌──┘
 * │ ─┤ ─┤       │ ─┤ ─┤
 * └──┴──┘       └──┴──┘
 * 神兽保佑
 * 代码无BUG!
 */


/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: caixq
 * Date: 2019-03-04
 * Time: 下午3:51
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //    @Autowired
//    private UserDetailsService myUserDetailsService;
    @Autowired
    private ObjectMapper mapper;
    @Autowired
    private AuthenticationAccessDeniedHandler accessDeniedHandler;
//    @Autowired
//    private CorsConfiguration corsConfiguration;

    @Autowired
    private UserDetailService userDetailService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //  允许所有用户访问"/"和"/index.html"
        http
                .authorizeRequests()
                .antMatchers("/", "/index.html").permitAll()
                .anyRequest()
                .authenticated()   // 其他地址的访问均需验证权限
                .and()
                .formLogin()
                .loginPage("/user/lg")
                .loginProcessingUrl("/login")
                .usernameParameter("userName").passwordParameter("password").permitAll()
                .failureHandler((request, response, e) -> {
                    WebResult result = new WebResult();
                    result.setErrorCode(1);
                    if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
                        result.setMsg("用户名或密码输入错误，登录失败!");
                    } else {
                        result.setMsg("登录失败!");
                    }
                    returnWebResult(request, response,result);

                }).successHandler((request, response, authentication) -> {
                    WebResult result = new WebResult();
                    result.setMsg("登陆成功");
                    result.setData(authentication);
                    returnWebResult(request, response,result);
                }
                ).and()
                .logout()
                .logoutSuccessHandler((request, response, authentication) -> {
                    WebResult result = new WebResult();
                    result.setMsg("登出成功");
                    result.setData(authentication);
                    returnWebResult(request, response,result);
                })
                .permitAll().and()
                .csrf().disable()
                .cors()//.configurationSource(request -> corsConfiguration)
                .and()
                .exceptionHandling().accessDeniedHandler((request, response, e) -> {
                    WebResult result=new WebResult();
                    result.setErrorCode(1);
                    result.setMsg("权限不足");
                    returnWebResult(request, response,result);
                });

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/static/**");
        super.configure(web);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
            }

            /**
             * @param charSequence 明文
             * @param s 密文
             * @return
             */
            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
            }
        };
    }


    public void returnWebResult(HttpServletRequest request,HttpServletResponse response,WebResult result) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        /**
         * 此接口允许所有跨域
         * */
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "*");

        PrintWriter out = response.getWriter();
        out.write(mapper.writeValueAsString(result));
        out.flush();
        out.close();
    }

}
